package com.lw;

import com.lw.config.GameState;
import com.lw.obj.BodyObj;
import com.lw.obj.FoodObj;
import com.lw.obj.GameObj;
import com.lw.obj.HeadObj;
import com.lw.utils.GameUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.ArrayList;

/**
 * 游戏窗口
 * 坐标系：
 * X轴 从左到右
 * Y轴 从上到下
 */
public class GameWin extends JFrame {

    //双缓存图片
    Image bufferImage = null;

    private static final int winWidth = 800; //窗口宽
    private static final int winHeight = 600;//窗口高

    //分数
    public static int score = 0;

    //游戏状态
    public static GameState state = GameState.NOT_STARTED;

    //蛇头
    HeadObj headObj = new HeadObj(winWidth / 2, winHeight / 2, this);

    //蛇身集合
    public List<BodyObj> bodyObjList = new ArrayList<>();

    //食物
    public FoodObj foodObj = new FoodObj().getFood();

    private void printBodyListLocation() {
        System.out.println();
        System.out.print(String.format("蛇头(%d,%d)", headObj.getX(), headObj.getY()));
        for (int i = 0; i < bodyObjList.size(); i++) {
            BodyObj bodyObj = bodyObjList.get(i);
            System.out.print("<--" + i + " (" + bodyObj.getX() + "," + bodyObj.getY() + ")");
        }
    }

    @Override
    public void paint(Graphics g) {
        //初始化双缓存图片
        if (bufferImage == null) {
            bufferImage = this.createImage(winWidth, winHeight);
        }
        Graphics gImage = bufferImage.getGraphics();

        gImage.setColor(Color.gray);//灰色背景
        gImage.fillRect(0, 0, winWidth, winHeight);
        //画网格线
        gImage.setColor(Color.black);
//        g.drawLine(0,60,600,60);// (0,60) -> (600,60) 起点到终点坐标的线
        for (int i = 0; i < 20; i++) {//如果右边那条线没有，可以改为21
            gImage.drawLine(0, i * 30, 600, i * 30);//绘制横线
            gImage.drawLine(i * 30, 0, i * 30, 600);//绘制纵线
        }

        printBodyListLocation();

        /*
        此处要注意，必须是先绘制蛇身，再绘制蛇头。
        因为蛇身第一个数据和蛇头相同，先绘制蛇头时，蛇身后绘制就把蛇头挡住了。
         */
        //绘制蛇身
        for (int i = bodyObjList.size() - 1; i >= 0; i--) {
            bodyObjList.get(i).paintSelf(gImage);
        }

        //绘制蛇头
        headObj.paintSelf(gImage);

        //绘制食物
        foodObj.paintSelf(gImage);

        //绘制关卡
        GameUtils.drawWord(gImage, String.format("第%d关", GameUtils.level), Color.orange, 40, 630, 240);

        //绘制分数
        GameUtils.drawWord(gImage, score + "分", Color.blue, 50, 650, 320);

        //绘制提示语
        gImage.setColor(Color.gray);
        prompt(gImage);

        //将双缓存的图片绘制到主窗口
        g.drawImage(bufferImage, 0, 0, null);
    }

    /**
     * 绘制提示语
     *
     * @param g
     */
    void prompt(Graphics g) {
        if (state == GameState.NOT_STARTED) {//游戏未开始
            g.fillRect(120, 240, 400, 70);
            GameUtils.drawWord(g, "按下空格开始游戏", Color.yellow, 35, 150, 290);
        } else if (state == GameState.PAUSED) {
            g.fillRect(120, 240, 400, 70);
            GameUtils.drawWord(g, "    游戏暂停    ", Color.yellow, 35, 150, 290);
        } else if (state == GameState.COMPLETED) {
            g.fillRect(120, 240, 400, 70);
            if (GameUtils.level == GameUtils.MAX_LEVEL) {
                GameUtils.drawWord(g, "    游戏通关   ", Color.green, 35, 150, 290);
            } else {
                GameUtils.drawWord(g, "按下空格开始下一关", Color.green, 35, 150, 290);
            }
        } else if (state == GameState.FAILED) {
            g.fillRect(120, 240, 400, 70);
            GameUtils.drawWord(g, "游戏失败，按空格重新开始", Color.red, 35, 150, 290);
        }
    }

    /**
     * 游戏重置
     */
    void resetGame() {
        //关闭当前窗口，开启新窗口
        this.dispose();
        GameWin.score = 0;
        main(new String[]{});
    }

    /**
     * 窗口加载
     */
    public void launch() {
        this.setVisible(true);//设置窗口可见
        this.setSize(winWidth, winHeight);
        this.setLocationRelativeTo(null);//设置窗口位置：屏幕居中
        this.setTitle("贪吃蛇");

        //蛇身初始化  注意蛇身和蛇头的x,y坐标要有间隔起来
        for (int i = 1; i < 3; i++) {
            bodyObjList.add(new BodyObj(winWidth / 2 - (30 * i), winHeight / 2, this));
        }

        //键盘事件
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                /*
                按下空格不同状态切换：
                未开始->游戏中
                游戏中->暂停
                暂停->游戏中
                失败->重启
                通关->下一关
                 */
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {//按下空格
                    switch (state) {
                        case NOT_STARTED -> state = GameState.IN_PROGRESS;
                        case IN_PROGRESS -> {
                            state = GameState.PAUSED;
                            repaint();//防止提示语没有绘制
                        }
                        case PAUSED -> state = GameState.IN_PROGRESS;
                        case FAILED -> state = GameState.RESET;
                        case COMPLETED -> state = GameState.NEXT_LEVEL;
                    }
                }
            }
        });

        while (true) {
            if (state == GameState.IN_PROGRESS) {
                repaint();//此方法会调用paint();
            } else if (state == GameState.RESET) {//失败重启
                state = GameState.NOT_STARTED;
                resetGame();
            } else if (state == GameState.NEXT_LEVEL && GameUtils.level < GameUtils.MAX_LEVEL) {//下一关
                state = GameState.IN_PROGRESS;
                GameUtils.level++;
                resetGame();
            }
            try {
                Thread.sleep(GameUtils.SPEED);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    public static void main(String[] args) {
        GameWin gameWin = new GameWin();
        gameWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gameWin.launch();
    }
}
